home *** CD-ROM | disk | FTP | other *** search
/ The Atari Compendium / The Atari Compendium (Toad Computers) (1994).iso / files / umich / network / ka9q / nhclb120.zoo / ftpcli.c < prev    next >
C/C++ Source or Header  |  1992-08-20  |  15KB  |  697 lines

  1. /* FTP client (interactive user) code */
  2. #define    LINELEN        128    /* Length of command buffer */
  3. #include <stdio.h>
  4. #ifdef __TURBOC__
  5. #include "fcntl.h"
  6. #endif
  7. #include "global.h"
  8. #include "config.h"
  9. #include "mbuf.h"
  10. #include "netuser.h"
  11. #include "icmp.h"
  12. #include "timer.h"
  13. #include "tcp.h"
  14. #include "ftp.h"
  15. #include "session.h"
  16. #include "cmdparse.h"
  17. #include "telnet.h"
  18. #include "iface.h"
  19. #include "ax25.h"
  20. #include "lapb.h"
  21. #include "finger.h"
  22. #include "nr4.h"
  23. #ifdef    BSD
  24. char *sprintf();
  25. #endif
  26. static ftpsetup();
  27. /* #ifdef __TURBOC__    */
  28. /* #include <fcntl.h>    */
  29. /* #endif        */
  30.  
  31. extern struct session *current;
  32. extern char nospace[];
  33. extern char badhost[];
  34. static char notsess[] = "Not an FTP session!\n";
  35. static char cantwrite[] = "Can't write %s\n";
  36. static char cantread[] = "Can't read %s\n";
  37.  
  38.  
  39. static int sndftpmsg();
  40. static void doreply();
  41. static void ftpccs();
  42. static void ftpcds();
  43. int donothing(),doftpcd(),dolist(),doget(),dols(),doput(),dotype(),doabort(),
  44.     domkdir(),dormdir();
  45.  
  46. struct cmds ftpabort[] = {
  47.     "",        donothing,    0,    NULLCHAR,        NULLCHAR,
  48.     "abort",    doabort,    0,    NULLCHAR,        NULLCHAR,
  49.     NULLCHAR,    NULLFP,        0,    "Only valid command is \"abort\"", NULLCHAR,
  50. };
  51.  
  52. struct cmds ftpcmds[] = {
  53.     "",        donothing,    0,    NULLCHAR,        NULLCHAR,
  54.     "cd",        doftpcd,    2,    "cd <directory>",    NULLCHAR,
  55.     "dir",        dolist,        0,    NULLCHAR,        NULLCHAR,
  56.     "list",        dolist,        0,    NULLCHAR,        NULLCHAR,
  57.     "get",        doget,        2,    "get remotefile <localfile>",    NULLCHAR,
  58.     "ls",        dols,        0,    NULLCHAR,        NULLCHAR,
  59.     "mkdir",    domkdir,    2,    "mkdir <directory>",    NULLCHAR,
  60.     "nlst",        dols,        0,    NULLCHAR,        NULLCHAR,
  61.     "rmdir",    dormdir,    2,    "rmdir <directory>",    NULLCHAR,
  62.     "put",        doput,        2,    "put localfile <remotefile>",    NULLCHAR,
  63.     "type",        dotype,        0,    NULLCHAR,        NULLCHAR,
  64.     NULLCHAR,    NULLFP,        0,     NULLCHAR,        NULLCHAR,
  65. };
  66.  
  67. /* Handle top-level FTP command */
  68. doftp(argc,argv)
  69. int argc;
  70. char *argv[];
  71. {
  72.     int32 resolve();
  73.     int ftpparse();
  74.     char *inet_ntoa();
  75.     void ftpccr(),ftpccs();
  76.     struct session *s;
  77.     struct ftp *ftp,*ftp_create();
  78.     struct tcb *tcb;
  79.     struct socket lsocket,fsocket;
  80.  
  81.     lsocket.address = ip_addr;
  82.     lsocket.port = lport++;
  83.     printf("Lookup ... ");
  84.     if((fsocket.address = resolve(argv[1])) == 0){
  85.         printf(badhost,argv[1]);
  86.         return 1;
  87.     }
  88.     if(argc < 3)
  89.         fsocket.port = FTP_PORT;
  90.     else
  91.         fsocket.port = atoi(argv[2]);
  92.     printf(" done. Trying to connect to %s ...\n",
  93.            inet_ntoa( fsocket.address));
  94.     /* Allocate a session control block */
  95.     if((s = newsession()) == NULLSESSION){
  96.         printf("Too many sessions\n");
  97.         return 1;
  98.     }
  99.     current = s;
  100.     if((s->name = malloc((unsigned)strlen(argv[1])+1)) != NULLCHAR)
  101.         strcpy(s->name,argv[1]);
  102.     s->type = FTP;
  103.     s->parse = ftpparse;
  104.  
  105.     /* Allocate an FTP control block */
  106.     if((ftp = ftp_create(LINELEN)) == NULLFTP){
  107.         s->type = FREE;
  108.         printf(nospace);
  109.         return 1;
  110.     }
  111.     ftp->state = STARTUP_STATE;
  112.     s->cb.ftp = ftp;    /* Downward link */
  113.     ftp->session = s;    /* Upward link */
  114.  
  115.     /* Now open the control connection */
  116.     tcb = open_tcp(&lsocket,&fsocket,TCP_ACTIVE,
  117.         0,ftpccr,NULLVFP,ftpccs,0,(char *)ftp);
  118.     ftp->control = tcb;
  119.     go();
  120.     return 0;
  121. }
  122. /* Parse user FTP commands */
  123. int
  124. ftpparse(line,len)
  125. char *line;
  126. int16 len;
  127. {
  128.     struct mbuf *bp;
  129.  
  130.     switch(current->cb.ftp->state){
  131.     case RECEIVING_STATE:
  132.     case SENDING_STATE:
  133.         /* The only command allowed in data transfer state is ABORT */
  134.         if(cmdparse(ftpabort,line) == -1){
  135.             printf("Transfer in progress; only ABORT is acceptable\n");
  136.         }
  137.         fflush(stdout);
  138.         break;
  139.     case COMMAND_STATE:
  140.         /* Save it now because cmdparse modifies the original */
  141.         bp = qdata(line,len);
  142.  
  143.         if(cmdparse(ftpcmds,line) == -1){
  144.             /* Send it direct */
  145.             if(bp != NULLBUF)
  146.                 send_tcp(current->cb.ftp->control,bp);
  147.             else
  148.                 printf(nospace);
  149.         } else {
  150.             free_p(bp);
  151.         }
  152.         fflush(stdout);
  153.         break;
  154.     case STARTUP_STATE:        /* Starting up autologin */
  155.         printf("Not connected yet, ignoring %s\r\n",line);
  156.         break;
  157.     case USER_STATE:        /* Got the user name */
  158.         line[len] = '\0';
  159.         return sndftpmsg(current->cb.ftp,"USER %s",line);
  160.     case PASS_STATE:        /* Got the password */
  161.         cooked();
  162.         line[len] = '\0';
  163.         return sndftpmsg(current->cb.ftp,"PASS %s",line);
  164.     }
  165.     return 0;
  166. }
  167. /* Handle null line to avoid trapping on first command in table */
  168. /*ARGSUSED*/
  169. static
  170. int
  171. donothing(argc,argv)
  172. int argc;
  173. char *argv[];
  174. {
  175. }
  176. /* Translate 'cd' to 'cwd' for convenience */
  177. /*ARGSUSED*/
  178. static
  179. int
  180. doftpcd(argc,argv)
  181. int argc;
  182. char *argv[];
  183. {
  184.     register struct ftp *ftp;
  185.  
  186.     ftp = current->cb.ftp;
  187.     return sndftpmsg(ftp,"CWD %s\r\n",argv[1]);
  188. }
  189. /* Translate 'mkdir' to 'xmkd' for convenience */
  190. /*ARGSUSED*/
  191. static
  192. int
  193. domkdir(argc,argv)
  194. int argc;
  195. char *argv[];
  196. {
  197.     register struct ftp *ftp;
  198.  
  199.     ftp = current->cb.ftp;
  200.     return sndftpmsg(ftp,"XMKD %s\r\n",argv[1]);
  201. }
  202. /* Translate 'rmdir' to 'xrmd' for convenience */
  203. /*ARGSUSED*/
  204. static
  205. int
  206. dormdir(argc,argv)
  207. int argc;
  208. char *argv[];
  209. {
  210.     register struct ftp *ftp;
  211.  
  212.     ftp = current->cb.ftp;
  213.     return sndftpmsg(ftp,"XRMD %s\r\n",argv[1]);
  214. }
  215. /* Handle "type" command from user */
  216. static
  217. int
  218. dotype(argc,argv)
  219. int argc;
  220. char *argv[];
  221. {
  222.     register struct ftp *ftp;
  223.  
  224.     ftp = current->cb.ftp;
  225.     if(argc < 2){
  226.         switch(ftp->type){
  227.         case IMAGE_TYPE:
  228.             printf("Image\n");
  229.             break;
  230.         case ASCII_TYPE:
  231.             printf("Ascii\n");
  232.             break;
  233.         }
  234.         return 0;
  235.     }
  236.     switch(*argv[1]){
  237.     case 'i':
  238.     case 'b':
  239.         ftp->type = IMAGE_TYPE;
  240.         sndftpmsg(ftp,"TYPE I\r\n");
  241.         break;
  242.     case 'a':
  243.         ftp->type = ASCII_TYPE;
  244.         sndftpmsg(ftp,"TYPE A\r\n");
  245.         break;
  246.     case 'l':
  247.         ftp->type = IMAGE_TYPE;
  248.         sndftpmsg(ftp,"TYPE L %s\r\n",argv[2]);
  249.         break;
  250.     default:
  251.         printf("Invalid type %s\n",argv[1]);
  252.         return 1;
  253.     }
  254.     return 0;
  255. }
  256. /* Start receive transfer. Syntax: get <remote name> [<local name>] */
  257. static
  258. doget(argc,argv)
  259. int argc;
  260. char *argv[];
  261. {
  262.     void ftpdr(),ftpcds();
  263.     char *remotename,*localname;
  264.     register struct ftp *ftp;
  265.     char *mode;
  266.  
  267.     ftp = current->cb.ftp;
  268.     if(ftp == NULLFTP){
  269.         printf(notsess);
  270.         return 1;
  271.     }
  272.     remotename = argv[1];
  273.     if(argc < 3)
  274.         localname = remotename;
  275.     else
  276.         localname = argv[2];
  277.  
  278.     if(ftp->fp != NULLFILE && ftp->fp != stdout)
  279.         fclose(ftp->fp);
  280.     ftp->fp = NULLFILE;
  281.  
  282.     if(ftp->type == IMAGE_TYPE) 
  283.         mode = binmode[WRITE_BINARY];
  284.     else
  285.         mode = "w";
  286.  
  287.     if((ftp->fp = fopen(localname,mode)) == NULLFILE){
  288.         printf(cantwrite,localname);
  289.         return 1;
  290.     }
  291.     ftp->state = RECEIVING_STATE;
  292.     ftpsetup(ftp,ftpdr,NULLVFP,ftpcds);
  293.  
  294.     /* Generate the command to start the transfer */
  295.     return sndftpmsg(ftp,"RETR %s\r\n",remotename);
  296. }
  297. /* List remote directory. Syntax: dir <remote directory/file> [<local name>] */
  298. static
  299. dolist(argc,argv)
  300. int argc;
  301. char *argv[];
  302. {
  303.     void ftpdr(),ftpcds();
  304.     register struct ftp *ftp;
  305.  
  306.     ftp = current->cb.ftp;
  307.     if(ftp == NULLFTP){
  308.         printf(notsess);
  309.         return 1;
  310.     }
  311.     if(ftp->fp != NULLFILE && ftp->fp != stdout)
  312.         fclose(ftp->fp);
  313.     ftp->fp = NULLFILE;
  314.  
  315.     if(argc < 3){
  316.         ftp->fp = stdout;
  317.     } else if((ftp->fp = fopen(argv[2],"w")) == NULLFILE){
  318.         printf(cantwrite,argv[2]);
  319.         return 1;
  320.     }
  321.     ftp->state = RECEIVING_STATE;
  322.     ftpsetup(ftp,ftpdr,NULLVFP,ftpcds);
  323.     /* Generate the command to start the transfer
  324.      * It's done this way to avoid confusing the 4.2 FTP server
  325.      * if there's no argument
  326.      */
  327.     if(argc > 1)
  328.         return sndftpmsg(ftp,"LIST %s\r\n",argv[1]);
  329.     else
  330.         return sndftpmsg(ftp,"LIST\r\n","");
  331. }
  332. /* Abbreviated (name only) list of remote directory.
  333.  * Syntax: ls <remote directory/file> [<local name>]
  334.  */
  335. static
  336. dols(argc,argv)
  337. int argc;
  338. char *argv[];
  339. {
  340.     void ftpdr(),ftpcds();
  341.     register struct ftp *ftp;
  342.  
  343.     ftp = current->cb.ftp;
  344.     if(ftp == NULLFTP){
  345.         printf(notsess);
  346.         return 1;
  347.     }
  348.     if(ftp->fp != NULLFILE && ftp->fp != stdout)
  349.         fclose(ftp->fp);
  350.     ftp->fp = NULLFILE;
  351.  
  352.     if(argc < 3){
  353.         ftp->fp = stdout;
  354.     } else if((ftp->fp = fopen(argv[2],"w")) == NULLFILE){
  355.         printf(cantwrite,argv[2]);
  356.         return 1;
  357.     }
  358.     ftp->state = RECEIVING_STATE;
  359.     ftpsetup(ftp,ftpdr,NULLVFP,ftpcds);
  360.     /* Generate the command to start the transfer */
  361.     if(argc > 1)
  362.         return sndftpmsg(ftp,"NLST %s\r\n",argv[1]);
  363.     else
  364.         return sndftpmsg(ftp,"NLST\r\n","");
  365. }
  366. /* Start transmit. Syntax: put <local name> [<remote name>] */
  367. static
  368. doput(argc,argv)
  369. int argc;
  370. char *argv[];
  371. {
  372.     void ftpdt(),ftpcds();
  373.     char *remotename,*localname;
  374.     char *mode;
  375.     struct ftp *ftp;
  376.  
  377.     if((ftp = current->cb.ftp) == NULLFTP){
  378.         printf(notsess);
  379.         return 1;
  380.     }
  381.     localname =